package com.erp.app.report.genericInquiry;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;

import com.erp.app.common.ProjectConstants;
import com.erp.app.report.genericInquiry.inquiryCriteria.beans.vo.InquiryCriteriaVO;
import com.erp.app.report.genericInquiry.inquiryDisplay.beans.vo.InquiryDisplayVO;
import com.erp.app.report.genericInquiry.inquiryMaster.beans.GenericInquiryMasterVO;
import com.erp.app.report.genericInquiry.inquiryOutput.beans.vo.InquiryOutputVO;
import com.erp.app.report.genericInquiry.inquirySp.beans.vo.InquirySpVO;
import com.erp.app.util.web.WebUtil;
import com.erp.framework.util.CommonUtil;

/**
 * A very basic Excel generation using HTML (Compatibility: Office2000+)
 *
 */
public class GenericExcelHtmlGenerator extends GenericFileGenerator {

    public GenericExcelHtmlGenerator(GenericInquirySearchForm form) {
		super(form);
	}

	public void generate(
			ActionMapping mapping, 
			HttpServletRequest request, 
			HttpServletResponse response, 
			ActionServlet servlet, 
			ActionErrors errors) throws Exception {
    	OutputStream dest = null;
        
        try {
            preprocess(request, response, servlet, errors);
            response.setStatus(HttpServletResponse.SC_OK);
            
            ByteArrayOutputStream baos = createReportByteArray(GenericInquiryConstants.JAVA_TYPE_HTM, false, mapping, request, response, servlet, errors);
            
            if (baos == null)
            	genContent(dest, request);
            else {
                dest = response.getOutputStream();
            	dump(dest, baos);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if(form.getReportResultList() != null) {
                form.getReportResultList().clear();
                form.setReportResultList(null);
            }
        }
	}

	protected void genContent(OutputStream os, HttpServletRequest request) throws IOException {
        HttpSession session = request.getSession(false);
        GenericInquiryMasterVO vo = form.getGenericInquiryMasterVO();
        Collection spList = vo.getLocalChilds(InquirySpVO.class);
        Collection displayList = vo.getLocalChilds(InquiryDisplayVO.class);
        Collection critList = vo.getLocalChilds(InquiryCriteriaVO.class);
        Collection rsltList = form.getReportResultList();
        InquiryDisplayVO displayVO = null;
        InquiryOutputVO rsltVO = null;
        InquirySpVO spVO = (InquirySpVO)spList.iterator().next();
        InquiryCriteriaVO critVO = null;
        
        BufferedOutputStream bos = new BufferedOutputStream(os);
        OutputStreamWriter osw = new OutputStreamWriter(bos);
        try {
			osw.write("<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"\n");
			osw.write("xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\n");
		    osw.write("xmlns=\"http://www.w3.org/TR/REC-html40\">\n");
		    osw.write("\n");
		    osw.write("<head>\n");
		    osw.write("<meta http-equiv=Content-Type content=\"text/html; charset=ISO-8859-1\">\n");
		    osw.write("<meta name=ProgId content=Excel.Sheet>\n");
		    osw.write("<meta name=Generator content=\"Microsoft Excel 9\">\n");
		    osw.write("<!--[if gte mso 9]><xml>\n");
		    osw.write("<o:DocumentProperties>\n");
		    String date_str = CommonUtil.dateToString(new Date(), "yyyy-MM-dd'T'hh:mm:ss'Z'");
		    osw.write("<o:Created>" + date_str + "</o:Created>\n");
		    osw.write("</o:DocumentProperties>\n");
		    osw.write("</xml><![endif]-->\n");
		    osw.write("<style>\n");
		    osw.write("<!--table\n");
		    osw.write("\t{mso-displayed-decimal-separator:\"\\.\";\n");
		    osw.write("\tmso-displayed-thousand-separator:\"\\,\";}\n");
		    osw.write("@page\n");
		    osw.write("\t{margin:1.0in .75in 1.0in .75in;\n");
		    osw.write("\tmso-header-margin:.5in;\n");
		    osw.write("\tmso-footer-margin:.5in;}\n");
		    osw.write("tr\n");
	    	osw.write("\t{mso-height-source:auto;\n");
	    	osw.write("\tmso-ruby-visibility:none;}\n");
		    osw.write("col\n");
	    	osw.write("\t{mso-width-source:auto;\n");
	    	osw.write("\tmso-ruby-visibility:none;}\n");
		    osw.write("br\n");
	    	osw.write("\t{mso-data-placement:same-cell;}\n");
		    osw.write(".style0\n");
		    osw.write("\t{mso-number-format:General;\n");
		    osw.write("\ttext-align:general;\n");
		    osw.write("\tvertical-align:bottom;\n");
		    osw.write("\twhite-space:nowrap;\n");
		    osw.write("\tmso-rotate:0;\n");
		    osw.write("\tmso-background-source:auto;\n");
	    	osw.write("\tmso-pattern:auto;\n");
	    	osw.write("\tcolor:windowtext;\n");
	    	osw.write("\tfont-size:10.0pt;\n");
	    	osw.write("\tfont-weight:400;\n");
	    	osw.write("\tfont-style:normal;\n");
	    	osw.write("\ttext-decoration:none;\n");
	    	osw.write("\tfont-family:Arial, sans-serif;\n");
	    	osw.write("\tmso-font-charset:0;\n");
	    	osw.write("\tborder:none;\n");
	    	osw.write("\tmso-protection:locked visible;\n");
	    	osw.write("\tmso-style-name:general;\n");
	    	osw.write("\tmso-style-id:0;}\n");
		    osw.write("td\n");
			osw.write("\t{mso-style-parent:style0;\n");
			osw.write("\tpadding-top:1px;\n");
			osw.write("\tpadding-right:1px;\n");
			osw.write("\tpadding-left:1px;\n");
			osw.write("\tmso-ignore:padding;\n");
			osw.write("\tcolor:windowtext;\n");
			osw.write("\tfont-size:9.0pt;\n");
			osw.write("\tfont-weight:400;\n");
			osw.write("\tfont-style:normal;\n");
			osw.write("\ttext-decoration:none;\n");
			osw.write("\tfont-family:Arial, sans-serif;\n");
			osw.write("\tmso-font-charset:0;\n");
			osw.write("\tmso-number-format:General;\n");
			osw.write("\ttext-align:general;\n");
			osw.write("\tvertical-align:bottom;\n");
			osw.write("\tborder:none;\n");
			osw.write("\tmso-background-source:auto;\n");
			osw.write("\tmso-pattern:auto;\n");
			osw.write("\tmso-protection:locked visible;\n");
			osw.write("\twhite-space:nowrap;\n");
			osw.write("\tmso-rotate:0;}\n");
			osw.write(".header\n");
			osw.write("\t{text-align:center;\n\tvertical-align:top;\n\twhite-space:normal;\n\tborder:.5pt solid black;}\n");
			osw.write("-->\n");
			osw.write("</style>\n");
			osw.write("<!--[if gte mso 9]><xml>\n");
			osw.write("<x:ExcelWorkbook>\n");
			osw.write("<x:ExcelWorksheets>\n");
			osw.write("<x:ExcelWorksheet>\n");
			osw.write("<x:Name>" + spVO.getInquiryName() + "</x:Name>\n");
			osw.write("<x:WorksheetOptions>\n");
			osw.write("<x:Print>\n");
			osw.write("<x:FitWidth>0</x:FitWidth>\n");
			osw.write("<x:FitHeight>0</x:FitHeight>\n");
			osw.write("<x:ValidPrinterInfo/>\n");
			osw.write("<x:PaperSizeIndex>9</x:PaperSizeIndex>\n");
			osw.write("<x:Scale>0</x:Scale>\n");
			osw.write("<x:HorizontalResolution>300</x:HorizontalResolution>\n");
			osw.write("<x:VerticalResolution>300</x:VerticalResolution>\n");
			osw.write("</x:Print>\n");
			osw.write("<x:Selected/>\n");
			osw.write("<x:ProtectContents>False</x:ProtectContents>\n");
			osw.write("<x:ProtectObjects>False</x:ProtectObjects>\n");
			osw.write("<x:ProtectScenarios>False</x:ProtectScenarios>\n");
			osw.write("</x:WorksheetOptions>\n");
			osw.write("</x:ExcelWorksheet>\n");
			osw.write("</x:ExcelWorksheets>\n");
			osw.write("<x:WindowTopX>360</x:WindowTopX>\n");
			osw.write("<x:WindowTopY>270</x:WindowTopY>\n");
			osw.write("<x:AcceptLabelsInFormulas/>\n");
			osw.write("<x:ProtectStructure>False</x:ProtectStructure>\n");
			osw.write("<x:ProtectWindows>False</x:ProtectWindows>\n");
			osw.write("</x:ExcelWorkbook>\n");
			osw.write("</xml><![endif]-->\n");
			osw.write("</head>\n\n");
			osw.write("<body link=blue vlink=purple>\n\n");
			osw.write("<table x:str border=0 cellpadding=0 cellspacing=0 " +
					"style='border-collapse:collapse;table-layout:fixed;'>");
			
			// Heading setup
			int column_size = displayList.size();
			
			for (int i = 0; i < column_size; i++) {	           
				osw.write("<col>\n");
			}
			
			// Title
			osw.write("<tr>\n");
			osw.write("<td>" + spVO.getInquiryName() + "</td>\n");
			fillEmptyCells(osw, column_size - 1);
			osw.write("</tr>\n");
			
			// Empty Row
			osw.write("<tr>\n");
			fillEmptyCells(osw, column_size);
			osw.write("</tr>\n");
			
			// Date
			Format formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss ");
	        String today = formatter.format(new Date());
			osw.write("<tr>\n<td>Date:</td><td>" + today + "</td>\n");
			fillEmptyCells(osw, column_size - 2);
			osw.write("</tr>\n");
			
			// Company Code
			osw.write("<tr>\n");
			osw.write("<td>Company:</td>\n<td>" + WebUtil.getAppropriateCompanyCode(session, null) + "</td>\n");
			fillEmptyCells(osw, column_size - 2);
			osw.write("</tr>\n");
			
			// Empty Row
			osw.write("<tr>\n");
			fillEmptyCells(osw, column_size);
			osw.write("</tr>\n");
			
			// Criteria
			int counter = 0;
			for (Iterator it = critList.iterator(); it.hasNext();) {
				critVO = (InquiryCriteriaVO)it.next();
				
				osw.write("<tr>\n");
				
				String field_type = critVO.getFieldType();
				
				if (GenericInquiryConstants.FIELD_TYPE_TEXT_FM_TO.equals(field_type) ||
	                    GenericInquiryConstants.FIELD_TYPE_TEXT_FM_TO_OC.equals(field_type)) {
					osw.write("<td>From " + critVO.getFieldName() + ":</td>");
	                osw.write("<td>" + form.getSrchFrom()[counter] + "</td>");
	                osw.write("<td>To " + critVO.getFieldName() + ":");
	                osw.write("<td>" + form.getSrchTo()[counter] + "</td>");
	                fillEmptyCells(osw, column_size - 4);
	            } else if (GenericInquiryConstants.FIELD_TYPE_DROP_DOWN.equals(field_type) ||
	                        GenericInquiryConstants.FIELD_TYPE_DROP_DOWN_OC.equals(field_type) ||
	                        GenericInquiryConstants.FIELD_TYPE_MULTIPLE_DROP_DOWN.equals(field_type) ||
	                        GenericInquiryConstants.FIELD_TYPE_MULTIBOX.equals(field_type) ||
	                        GenericInquiryConstants.FIELD_TYPE_MULTIBOX_HORIZONTAL.equals(field_type)) {
	            	osw.write("<td>" + critVO.getFieldName() + ":</td>");
	            	osw.write("<td>" + form.getSrchFromLabel()[counter] + "</td>");
	            	fillEmptyCells(osw, column_size - 2);
	            } else {
	            	osw.write("<td>" + critVO.getFieldName() + ":</td>");
	            	osw.write("<td>" + form.getSrchFrom()[counter] + "</td>");
	            	fillEmptyCells(osw, column_size - 2);
	            }
				
				osw.write("</tr>\n");
				counter++;
			}
			
			// 2x Empty Row
			osw.write("<tr>\n");
			fillEmptyCells(osw, column_size);
			osw.write("</tr>\n");
			osw.write("<tr>\n");
			fillEmptyCells(osw, column_size);
			osw.write("</tr>\n");
			
			osw.write("<tr>\n");
			for (Iterator it = displayList.iterator(); it.hasNext();) {
				displayVO = (InquiryDisplayVO)it.next();
				
				osw.write("<td>" + displayVO.getDispName() + "</td>");
			}
			osw.write("</tr>\n");
			
			String fieldNature = "";
			String fieldValue = "";
			
			for (Iterator it = rsltList.iterator(); it.hasNext();) {
				rsltVO = (InquiryOutputVO)it.next();
				counter = 0;
				
				osw.write("<tr>\n");
				for (Iterator _it = displayList.iterator(); _it.hasNext();) {
					displayVO = (InquiryDisplayVO)_it.next();
					fieldNature = CommonUtil.nullToString(displayVO.getFieldNature());
					fieldValue = CommonUtil.nullToString(rsltVO.getField(counter));
					
					String dispCode = displayVO.getDispCode();
					
					if (fieldNature.equals(GenericInquiryConstants.DATA_TYPE_NUMERIC)) {
						osw.write("<td>" + CommonUtil.stringRpl(fieldValue, ",", "") + "</td>");
	                } else if (fieldNature.equals(GenericInquiryConstants.DATA_TYPE_DATE)) {
	                	if (!CommonUtil.isEmpty(fieldValue)){
	                		try {
								osw.write("<td>" + CommonUtil.stringToDate(fieldValue, ProjectConstants.RPT_DATE_FORMAT, ProjectConstants.DEFAULT_LOCALE) + "</td>");
							} catch (ParseException e) {
								osw.write("<td>&nbsp;</td>");
							}
	                	} else {
	                		osw.write("<td>&nbsp;</td>");
	                	}
	                } else
	                    osw.write("<td>" + fieldValue + "</td>");
	                counter++;
				}
				osw.write("</tr>\n");
			}
			
			osw.write("</table></body></html>");
        } catch (IOException e) {
        	throw e;
        } finally {
        	osw.flush();
        	osw.close();
        }
    }
	
	private void fillEmptyCells(OutputStreamWriter osw, int n) throws IOException {
		for (int i = 0; i < n; i++)
			osw.write("<td>&nbsp;</td>");
	}

    protected void preprocess(HttpServletRequest request, HttpServletResponse response, ActionServlet servlet, ActionErrors errors) {
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-disposition", "attachment; filename=\"" + CommonUtil.toValidFileName(form.getFilename()) + ".xls\"");
    }

	protected ByteArrayOutputStream genContent(ActionMapping mapping, HttpServletRequest request, HttpServletResponse response, ActionServlet servlet, ActionErrors errors) throws Exception {
		throw new UnsupportedOperationException("Unused.");
	}
}
